// The code below is a stub. Just enough to satisfy the compiler.
// In order to pass the tests you can add-to or change any of this code.


#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub struct Robot {
    facing: Direction,
    position: (i32, i32),
}

impl Robot {
    pub fn new(x: i32, y: i32, d: Direction) -> Self {
        Robot {
            facing: d,
            position: (x, y),
        }
    }

    #[must_use]
    pub fn turn_right(self) -> Self {
        match self.facing {
            Direction::North => Robot::new(self.position.0, self.position.1, Direction::East),
            Direction::East => Robot::new(self.position.0, self.position.1, Direction::South),
            Direction::South => Robot::new(self.position.0, self.position.1, Direction::West),
            Direction::West => Robot::new(self.position.0, self.position.1, Direction::North),
        }
    }

    #[must_use]
    pub fn turn_left(self) -> Self {
        match self.facing {
            Direction::North => {
                Robot::new(self.position.0, self.position.1, Direction::West)
            }
            Direction::East => {
                Robot::new(self.position.0, self.position.1, Direction::North)
            }
            Direction::South => {
                Robot::new(self.position.0, self.position.1, Direction::East)
            }
            Direction::West => {
                Robot::new(self.position.0, self.position.1, Direction::South)
            }
        }
    }

    #[must_use]
    pub fn advance(self) -> Self {
        match self.facing {
            Direction::North => {
                Robot::new(self.position.0, self.position.1 + 1, self.facing)
            }
            Direction::East => {
                Robot::new(self.position.0 + 1, self.position.1, self.facing)
            }
            Direction::South => {
                Robot::new(self.position.0, self.position.1 - 1, self.facing)
            }
            Direction::West => {
                Robot::new(self.position.0 - 1, self.position.1, self.facing)
            }
        }
    }

    #[must_use]
    pub fn instructions(self, instructions: &str) -> Self {
        // let mut robot = self;
        fn ins(from: Robot, ins: char) -> Robot {
            match ins {
                'A' => from.advance(),
                'R' => from.turn_right(),
                'L' => from.turn_left(),
                _ => unreachable!(),
            }
        }

        let mut tmp = self;
        for c in instructions.chars() {
            tmp = ins(tmp, c);
        }
        tmp
    }

    pub fn position(&self) -> (i32, i32) {
        self.position
    }

    pub fn direction(&self) -> &Direction {
        &self.facing
    }
}


#[test]
fn at_origin_facing_north() {
    let robot = Robot::new(0, 0, Direction::North);
    assert_eq!(robot.position(), (0, 0));
    assert_eq!(robot.direction(), &Direction::North);
}
